home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / dev / misc / dialoglib.lha / element.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-08  |  10.3 KB  |  511 lines

  1. #include <intuition/intuition.h>
  2. #include <proto/utility.h>
  3. #include <clib/macros.h>
  4. #include "dialog.h"
  5. #ifdef DEBUG1
  6.     #include <stdio.h>
  7. #endif
  8.  
  9. typedef ULONG (*Callback)();
  10. VOID SetupHook( struct Hook *, Callback, VOID * );
  11. ULONG CallHook( struct Hook *, APTR, ... );
  12. ULONG CallHookA( struct Hook *, APTR, APTR );
  13.  
  14. VOID setMaxWidth( DialogElement *de, LONG space )
  15. {
  16.     de->maxWidth = MIN( space, MAX_SPACE );
  17. }
  18.  
  19. VOID setMaxHeight( DialogElement *de, LONG space )
  20. {
  21.     de->maxHeight = MIN( space, MAX_SPACE );
  22. }
  23.  
  24. VOID setMaxLeftExtent( DialogElement *de, LONG space )
  25. {
  26.     de->maxLeftExtent = MIN( space, MAX_SPACE );
  27. }
  28.  
  29. VOID setMaxRightExtent( DialogElement *de, LONG space )
  30. {
  31.     de->maxRightExtent = MIN( space, MAX_SPACE );
  32. }
  33.  
  34. VOID setMaxTopExtent( DialogElement *de, LONG space )
  35. {
  36.     de->maxTopExtent = MIN( space, MAX_SPACE );
  37. }
  38.  
  39. VOID setMaxBottomExtent( DialogElement *de, LONG space )
  40. {
  41.     de->maxBottomExtent = MIN( space, MAX_SPACE );
  42. }
  43.  
  44. VOID setMinWidth( DialogElement *de, LONG space )
  45. {
  46.     de->minWidth = MIN( space, MAX_SPACE );
  47. }
  48.  
  49. VOID setMinHeight( DialogElement *de, LONG space )
  50. {
  51.     de->minHeight = MIN( space, MAX_SPACE );
  52. }
  53.  
  54. VOID setMinLeftExtent( DialogElement *de, LONG space )
  55. {
  56.     de->minLeftExtent = MIN( space, MAX_SPACE );
  57. }
  58.  
  59. VOID setMinRightExtent( DialogElement *de, LONG space )
  60. {
  61.     de->minRightExtent = MIN( space, MAX_SPACE );
  62. }
  63.  
  64. VOID setMinTopExtent( DialogElement *de, LONG space )
  65. {
  66.     de->minTopExtent = MIN( space, MAX_SPACE );
  67. }
  68.  
  69. VOID setMinBottomExtent( DialogElement *de, LONG space )
  70. {
  71.     de->minBottomExtent = MIN( space, MAX_SPACE );
  72. }
  73.  
  74. LONG getMinWidth( DialogElement *de )
  75. {
  76.     return de->minWidth;
  77. }
  78.  
  79. LONG getMinHeight( DialogElement *de )
  80. {
  81.     return de->minHeight;
  82. }
  83.  
  84. LONG getMinLeftExtent( DialogElement *de )
  85. {
  86.     return de->minLeftExtent;
  87. }
  88.  
  89. LONG getMinRightExtent( DialogElement *de )
  90. {
  91.     return de->minRightExtent;
  92. }
  93.  
  94. LONG getMinTopExtent( DialogElement *de )
  95. {
  96.     return de->minTopExtent;
  97. }
  98.  
  99. LONG getMinBottomExtent( DialogElement *de )
  100. {
  101.     return de->minBottomExtent;
  102. }
  103.  
  104. LONG getMaxWidth( DialogElement *de )
  105. {
  106.     return de->maxWidth;
  107. }
  108.  
  109. LONG getMaxHeight( DialogElement *de )
  110. {
  111.     return de->maxHeight;
  112. }
  113.  
  114. LONG getMaxLeftExtent( DialogElement *de )
  115. {
  116.     return de->maxLeftExtent;
  117. }
  118.  
  119. LONG getMaxRightExtent( DialogElement *de )
  120. {
  121.     return de->maxRightExtent;
  122. }
  123.  
  124. LONG getMaxTopExtent( DialogElement *de )
  125. {
  126.     return de->maxTopExtent;
  127. }
  128.  
  129. LONG getMaxBottomExtent( DialogElement *de )
  130. {
  131.     return de->maxBottomExtent;
  132. }
  133.  
  134. VOID initDialogElementA( DialogElement *de, DialogElement *root, DialogCallback dc,
  135.     ULONG *error, struct TagItem *taglist )
  136. {
  137.     if( !de )
  138.         return;
  139.  
  140.     de->object = NULL;
  141.     de->taglist = NULL;
  142.  
  143.     if( *error != DIALOGERR_NO_ERROR )
  144.         return;
  145.  
  146.     de->taglist = CloneTagItems( taglist );
  147.     if( !de->taglist )
  148.     {
  149.         *error = DIALOGERR_NO_MEMORY;
  150.         return;
  151.     }
  152.     SetupHook( &de->hook, (Callback)dc, de );
  153.     setMinWidth( de, 0 );
  154.     setMinHeight( de, 0 );
  155.     setMinLeftExtent( de, 0 );
  156.     setMinRightExtent( de, 0 );
  157.     setMinTopExtent( de, 0 );
  158.     setMinBottomExtent( de, 0 );
  159.     setMaxWidth( de, MAX_SPACE );
  160.     setMaxHeight( de, MAX_SPACE );
  161.     setMaxLeftExtent( de, MAX_SPACE );
  162.     setMaxRightExtent( de, MAX_SPACE );
  163.     setMaxTopExtent( de, MAX_SPACE );
  164.     setMaxBottomExtent( de, MAX_SPACE );
  165.     de->root = root;
  166. }
  167.  
  168. VOID initDialogElement( DialogElement *de, DialogElement *root, DialogCallback dc,
  169.     ULONG *error, ULONG first, ... )
  170. {
  171.     initDialogElementA( de, root, dc, error, (struct TagItem *)&first );
  172. }
  173.  
  174. VOID cleanupDialogElement( DialogElement *de )
  175. {
  176.     if( !de )
  177.         return;
  178.  
  179.     if( de->taglist )
  180.         FreeTagItems( de->taglist );
  181. }
  182.  
  183. VOID setupDialogElement( DialogElement *de )
  184. {
  185.     if( !de )
  186.         return;
  187.  
  188.     de->idcmp_mask = GetTagData( DA_MatchEventClasses, 0, de->taglist );
  189.     CallHook( &de->hook, de, DIALOGM_SETUP );
  190. #ifdef DEBUG1
  191.     printf( "setupDialogElement : "
  192.     "de %08lx, min width %d, height %d, left %d, right %d, top %d, bottom %d\n",
  193.         de,
  194.         getMinWidth( de ),
  195.         getMinHeight( de ),
  196.         getMinLeftExtent( de ),
  197.         getMinRightExtent( de ),
  198.         getMinTopExtent( de ),
  199.         getMinBottomExtent( de ) );
  200. #endif
  201. }
  202.  
  203. ULONG getDialogElementStructure( DialogElement *de )
  204. {
  205.     if( !de )
  206.         return 0;
  207.  
  208.     return CallHook( &de->hook, de, DIALOGM_GETSTRUCT );
  209. }
  210.  
  211. VOID prepareLayoutX( LayoutMessage *lm, LONG x )
  212. {
  213.     if( !lm )
  214.         return;
  215.  
  216.     lm->lm_X = x;
  217. }
  218.  
  219. VOID prepareLayoutY( LayoutMessage *lm, LONG y )
  220. {
  221.     if( !lm )
  222.         return;
  223.  
  224.     lm->lm_Y = y;
  225. }
  226.  
  227. VOID prepareLayoutHBaseline( LayoutMessage *lm, LONG top, LONG bottom )
  228. {
  229.     if( !lm )
  230.         return;
  231.  
  232.     lm->lm_Top = top;
  233.     lm->lm_Bottom = bottom;
  234. }
  235.  
  236. VOID prepareLayoutNoHBaseline( LayoutMessage *lm, LONG height )
  237. {
  238.     if( !lm )
  239.         return;
  240.  
  241.     lm->lm_Height = height;
  242. }
  243.  
  244. VOID prepareLayoutVBaseline( LayoutMessage *lm, LONG left, LONG right )
  245. {
  246.     if( !lm )
  247.         return;
  248.  
  249.     lm->lm_Left = left;
  250.     lm->lm_Right = right;
  251. }
  252.  
  253. VOID prepareLayoutNoVBaseline( LayoutMessage *lm, LONG width )
  254. {
  255.     if( !lm )
  256.         return;
  257.  
  258.     lm->lm_Width = width;
  259. }
  260.  
  261. ULONG layoutDialogElement( DialogElement *de, LayoutMessage *lm, APTR prevptr )
  262. {
  263.     ULONG error;
  264.  
  265.     if( !de )
  266.         return DIALOGERR_BAD_ARGS;
  267.     if( !lm )
  268.         return DIALOGERR_BAD_ARGS;
  269.  
  270.     lm->lm_MethodID = DIALOGM_LAYOUT;
  271.     lm->lm_PreviousPtr = prevptr;
  272.     error = CallHookA( &de->hook, de, lm );
  273.     return error;
  274. }
  275.  
  276. VOID clearDialogElement( DialogElement *de )
  277. {
  278.     if( !de )
  279.         return;
  280.  
  281.     CallHook( &de->hook, de, DIALOGM_CLEAR );
  282. }
  283.  
  284. static ULONG matchSpecialEvent( DialogElement *de, struct IntuiMessage *imsg )
  285. {
  286.     if( !de )
  287.         return 0;
  288.  
  289.     return imsg->Class & GetTagData( DA_MatchEventClasses, 0, de->taglist );
  290. }
  291.  
  292. DialogElement *mapDialogEvent( DialogElement *de, struct IntuiMessage *imsg )
  293. {
  294.     DialogElement *match = NULL;
  295.  
  296.     if( matchSpecialEvent( de, imsg ) )
  297.         match = de;
  298.     else
  299.         match = (DialogElement *)CallHook( &de->hook, de, DIALOGM_MATCH, imsg );
  300.  
  301.     return match;
  302. }
  303.  
  304. static LONG countComplementA( struct TagItem *list, struct TagItem *set )
  305. {
  306.     struct TagItem *tag, *tstate;
  307.     LONG count;
  308.  
  309.     count = 0;
  310.     tstate = list;
  311.     while( tag = NextTagItem( &tstate ) )
  312.         if( !FindTagItem( tag->ti_Tag, set ) )
  313.             count++;
  314.     return count;
  315. }
  316.  
  317. static LONG countComplement( struct TagItem *list, ULONG first )
  318. {
  319.     return countComplementA( list, (struct TagItem *)&first );
  320. }
  321.  
  322. ULONG setDialogElementAttrsA( DialogElement *de,
  323.     struct Window *window, struct Requester *requester, struct TagItem *taglist )
  324. {
  325.     struct TagItem *tag, *old, *update, *new, *tstate;
  326.     LONG count;
  327.     ULONG result = FALSE;
  328.  
  329.     /* determine number of items in new (combined) tag list */
  330.     count = countComplement( de->taglist, TAG_DONE ) +
  331.             countComplementA( taglist, de->taglist );
  332.  
  333.     /* allocate new tag list */
  334.     new = AllocateTagItems( count );
  335.     if( !new )
  336.         goto termination;
  337.  
  338.     /* now merge old and new list together */
  339.     tag = new;
  340.     tstate = de->taglist;
  341.     while( old = NextTagItem( &tstate ) )
  342.     {
  343.         tag->ti_Tag = old->ti_Tag;
  344.         if( update = FindTagItem( old->ti_Tag, taglist ) )
  345.             tag->ti_Data = update->ti_Data;
  346.         else
  347.             tag->ti_Data = old->ti_Data;
  348.         tag++;
  349.     }
  350.     FreeTagItems( de->taglist );
  351.     de->taglist = new;
  352.     CallHook( &de->hook, de, DIALOGM_SETATTRS, window, requester );
  353.     result = TRUE;
  354. termination:
  355.     return result;
  356. }
  357.  
  358. ULONG setDialogElementAttrs( DialogElement *de,
  359.     struct Window *window, struct Requester *requester, ULONG firsttag, ... )
  360. {
  361.     return setDialogElementAttrsA( de, window, requester, (struct TagItem *)&firsttag );
  362. }
  363.  
  364. ULONG prepareMemberLayoutH( LayoutMessage *message,
  365.     DialogElement *de, DialogElement *member, LayoutMessage *lm )
  366. {
  367.     ULONG substructure;
  368.     LONG alignment, x, left, right, width;
  369.  
  370.     if( !de )
  371.         return 0;
  372.     if( !lm )
  373.         return 0;
  374.  
  375.     alignment = GetTagData( DA_Alignment, 0, de->taglist );
  376.  
  377.     x = lm->lm_X;
  378.     substructure = getDialogElementStructure( member );
  379.     if( substructure & DESF_VBaseline )
  380.     {
  381.         if( de->structure & DESF_VBaseline )
  382.         {
  383.             left = getMaxLeftExtent( member );
  384.             left = MIN( lm->lm_Left, left );
  385.             right = getMaxRightExtent( member );
  386.             right = MIN( lm->lm_Right, right );
  387.         }
  388.         else
  389.         {
  390.             LONG minleft, minright, spare, white;
  391.  
  392.             minleft = getMinLeftExtent( member );
  393.             minright = getMinRightExtent( member );
  394.             white = lm->lm_Width - minleft - minright;
  395.             left = getMaxLeftExtent( member ) - minleft;
  396.             right = getMaxRightExtent( member ) - minright;
  397.             spare = left + right;
  398.             if( white > spare )
  399.                 white = spare;
  400.             left = minleft + ( ( spare ) ? ( left * white ) / spare : 0 );
  401.             right = minright + ( ( spare ) ? ( right * white ) / spare : 0 );
  402.             switch( alignment )
  403.             {
  404.             case -1:
  405.                 x += left;
  406.                 break;
  407.             case 0:
  408.                 x += ( lm->lm_Width + left - right ) / 2;
  409.                 break;
  410.             case +1:
  411.                 x += lm->lm_Width - right;
  412.                 break;
  413.             }
  414.         }
  415.         prepareLayoutVBaseline( message, left, right );
  416.     }
  417.     else
  418.     {
  419.         width = getMaxWidth( member );
  420.         width = MIN( lm->lm_Width, width );
  421.         prepareLayoutNoVBaseline( message, width );
  422.         switch( alignment )
  423.         {
  424.         case -1:
  425.             break;
  426.         case 0:
  427.             x += ( lm->lm_Width - width ) / 2;
  428.             break;
  429.         case +1:
  430.             x += lm->lm_Width - width;
  431.             break;
  432.         }
  433.     }
  434.     prepareLayoutX( message, x );
  435.     return substructure;
  436. }
  437.  
  438. ULONG prepareMemberLayoutV( LayoutMessage *message,
  439.     DialogElement *de, DialogElement *member, LayoutMessage *lm )
  440. {
  441.     ULONG substructure;
  442.     LONG alignment, y, top, bottom, height;
  443.  
  444.     if( !de )
  445.         return 0;
  446.     if( !lm )
  447.         return 0;
  448.  
  449.     alignment = GetTagData( DA_Alignment, 0, de->taglist );
  450.  
  451.     y = lm->lm_Y;
  452.     substructure = getDialogElementStructure( member );
  453.     if( substructure & DESF_HBaseline )
  454.     {
  455.         if( de->structure & DESF_HBaseline )
  456.         {
  457.             top = getMaxTopExtent( member );
  458.             top = MIN( lm->lm_Top, top );
  459.             bottom = getMaxBottomExtent( member );
  460.             bottom = MIN( lm->lm_Bottom, bottom );
  461.         }
  462.         else
  463.         {
  464.             LONG mintop, minbottom, spare, white;
  465.  
  466.             mintop = getMinTopExtent( member );
  467.             minbottom = getMinBottomExtent( member );
  468.             white = lm->lm_Height - mintop - minbottom;
  469.             top = getMaxTopExtent( member ) - mintop;
  470.             bottom = getMaxBottomExtent( member ) - minbottom;
  471.             spare = top + bottom;
  472.             if( white > spare )
  473.                 white = spare;
  474.             top = mintop + ( ( spare ) ? ( top * white ) / spare : 0 );
  475.             bottom = minbottom + ( ( spare ) ? ( bottom * white ) / spare : 0 );
  476.             switch( alignment )
  477.             {
  478.             case -1:
  479.                 y += top;
  480.                 break;
  481.             case 0:
  482.                 y += ( lm->lm_Height + top - bottom ) / 2;
  483.                 break;
  484.             case +1:
  485.                 y += lm->lm_Height - bottom;
  486.                 break;
  487.             }
  488.         }
  489.         prepareLayoutHBaseline( message, top, bottom );
  490.     }
  491.     else
  492.     {
  493.         height = getMaxHeight( member );
  494.         height = MIN( lm->lm_Height, height );
  495.         prepareLayoutNoHBaseline( message, height );
  496.         switch( alignment )
  497.         {
  498.         case -1:
  499.             break;
  500.         case 0:
  501.             y += ( lm->lm_Height - height ) / 2;
  502.             break;
  503.         case +1:
  504.             y += lm->lm_Height - height;
  505.             break;
  506.         }
  507.     }
  508.     prepareLayoutY( message, y );
  509.     return substructure;
  510. }
  511.